
import Debug.QuickCheck
import System.Time
import System.CPUTime

-----------------------------------------------------------------------

ones :: [Integer]
ones = 1 : ones

-----------------------------------------------------------------------

dyrt :: Integer -> Integer
dyrt n | n <= 1    = 1
       | otherwise = dyrt (n-1) + dyrt (n-2)

choice :: Bool -> a -> a -> a
choice False x y = x
choice True  x y = y

examp1 = choice False 17 (dyrt 99)

-----------------------------------------------------------------------

strange :: Bool -> Integer
strange False = 17
strange True  = 17

examp2 = strange undefined

-----------------------------------------------------------------------

replicate' :: Int -> a -> [a]
replicate' n x = take n (repeat x)

-----------------------------------------------------------------------

pairs :: [a] -> [(a,a)]
pairs xs = xs `zip` tail (cycle xs)

-- alternative definition
pairs' :: [a] -> [(a,a)]
pairs' xs = xs `zip` tail (xs ++ xs)

-----------------------------------------------------------------------

group :: Int -> [a] -> [[a]]
group n = takeWhile (not . null)
        . map (take n)
        . iterate (drop n)

-----------------------------------------------------------------------

data Labyrinth
  = Crossroad
  { what  :: String
  , left  :: Labyrinth
  , right :: Labyrinth
  }
 deriving ( Eq, Show )

labyrinth :: Labyrinth
labyrinth = start
 where
  start  = Crossroad "start"  forest town
  town   = Crossroad "town"   start  forest
  forest = Crossroad "forest" town   exit
  exit   = Crossroad "exit"   exit   exit

-----------------------------------------------------------------------

{-
Two alternative solutions. Which one's faster?
-}

-- prime numbers using Eratosthenes' sieve 
primes :: [Integer]
primes = sieve [2..]
 where
  sieve (x:xs) = x : sieve [ y | y <- xs, not (x `divides` y) ]

-- prime numbers, checking for each x that all prime numbers up to the square
-- root of x do not divide the number
primes' :: [Integer]
primes' = 2 : [ x | x <- [3..], and [ not (y `divides` x) | y <- upToRoot x ] ]
 where
  root       = floor . sqrt . fromInteger
  upToRoot x = takeWhile (<= root x) primes'

-- divides
divides :: Integer -> Integer -> Bool
a `divides` b = b `mod` a == 0

-- comparison
whichOne =
  do t1 <- getCPUTime
     print (take n primes)
     t2 <- getCPUTime
     print (take n primes')
     t3 <- getCPUTime
     putStrLn ( (if t2-t1 < t3-t2 then "primes" else "primes'")
             ++ " is faster!"
              )
 where
  n = 500
  
-----------------------------------------------------------------------

  
